﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Text;
using System.IO;
using System.Net;
using System.Data.SqlClient;
using System.Data;

namespace sdamarketing
{
    public class Analisys
    {
            //broj na pojavuvanja na termin do odreden dokument - Fi
            public int frekfencijaNaTerminVoDokument(String termin, String dokument)
            {
                int broj = 0;
                String[] pomDokument = dokument.Split(' ');
                for (int i = 0; i < pomDokument.Length; i++)
                {
                    if (pomDokument[i].Contains(termin) && !termin.Equals(""))
                        broj++;
                }
                return broj;
            }

            //broj na dokumenti sto go sodrzat odreden termin - Di
            public int brDokumentiStoSodrzatTermin(String termin, String[] dokument)
            {
                int broj = 0;
                for (int i = 0; i < dokument.Length; i++)
                {
                    if (dokument[i].Contains(termin))
                        broj++;
                }
                return broj;
            }

            //formula za dobivanje na element na matricata A
            //Fij-frekfencija na termin vo dokument, D-vkupen br. na dokumenti, Di-br. na dokumenti sto go sodrzat terminot
            public double elementNaA(int Fij, int D, int Di)
            {
                double rezultat;
                if (Math.Abs(Di) > 0)
                    rezultat = Fij * Math.Round((Double)D / Di, 5);//Math.Round((Double)Math.Log10(D/Di), 5);
                else
                    rezultat = 0;
                return rezultat;
            }

            //Evklidovi dolzini na vektorite, L2-normalizacija (se koristat za dobivanje na elementite na A(u))
            public double[] dolziniNaVektoriteNaA(double[][] matricaA)
            {
                double[] dolzini = new double[matricaA[0].Length];
                double suma = 0;
                for (int j = 0; j < matricaA[0].Length; j++)
                {
                    for (int i = 0; i < matricaA.Length; i++)
                    {
                        suma += Math.Pow(matricaA[i][j], 2);
                    }
                    dolzini[j] = Math.Round((Double)Math.Sqrt(suma), 5);
                    suma = 0;
                }
                return dolzini;
            }

            //Evklidovi dolzini na vektorite, L2-normalizacija (se koristat za dobivanje na elementite na Q(u))
            public double dolzinaNaVektorotNaQ(double[] qVektor)
            {
                double dolzina;
                double suma = 0;
                for (int i = 0; i < qVektor.Length; i++)
                {
                    suma += Math.Pow(qVektor[i], 2);
                }
                dolzina = Math.Round((Double)Math.Sqrt(suma), 5);
                return dolzina;
            }

            //kreiranje na query vektorot
            public double[] queryVektor(String[] termini, String query)
            {
                double[] qVektor = new double[termini.Length];

                for (int i = 0; i < qVektor.Length; i++)
                {
                    if (query.ToUpper().Contains(termini[i]))
                        qVektor[i] = 1;
                    else
                        qVektor[i] = 0;
                }
                return qVektor;
            }

            //kreiranje na vektorot q(u)
            public double[] queryVektorU(double[] qVektor)
            {
                double dolzinaNaVektor = dolzinaNaVektorotNaQ(qVektor);
                double[] pomVektor = new double[qVektor.Length];
                for (int i = 0; i < pomVektor.Length; i++)
                {
                    pomVektor[i] = Math.Round((Double)qVektor[i] / dolzinaNaVektor, 5);
                }
                return pomVektor;
            }

            //kreiranje ma matricata A
            public double[][] matricaA(String[] termini, String[] dokumenti)
            {
                int frekfencija;
                int Di;
                int D = dokumenti.Length;
                double[][] matricaA = new double[termini.Length][];
                for (int i = 0; i < termini.Length; i++)
                {
                    matricaA[i] = new double[dokumenti.Length];
                    for (int j = 0; j < dokumenti.Length; j++)
                    {
                        frekfencija = frekfencijaNaTerminVoDokument(termini[i], dokumenti[j]);
                        Di = brDokumentiStoSodrzatTermin(termini[i], dokumenti);
                        matricaA[i][j] = elementNaA(frekfencija, D, Di);
                    }
                }
                return matricaA;
            }

            //kreiranje na matricata A(u)
            public double[][] matricaAu(double[][] matricaA)
            {
                double[] dolziniNaVektori = dolziniNaVektoriteNaA(matricaA);
                double[][] pomMatrica = new double[matricaA.Length][];

                for (int i = 0; i < matricaA.Length; i++)
                {
                    pomMatrica[i] = new double[matricaA[0].Length];
                    for (int j = 0; j < matricaA[0].Length; j++)
                    {
                        pomMatrica[i][j] = Math.Round((Double)(matricaA[i][j] / dolziniNaVektori[j]), 5);
                    }

                }
                return pomMatrica;
            }

            //mnozenje na matrici (q(u)*A(u))
            public double[] mnozenjeNaMatrici(double[] qVektorU, double[][] matricaAu)
            {
                double[] pomMatrica = new double[matricaAu[0].Length];
                for (int k = 0; k < matricaAu[0].Length; k++)
                {
                    pomMatrica[k] = 0;
                    for (int j = 0; j < matricaAu.Length; j++)
                    {
                        pomMatrica[k] += Math.Round((Double)qVektorU[j] * matricaAu[j][k], 5);
                    }
                }
                return pomMatrica;
            }

            //izvlekuvanjena isti termini od dokuentite
            public String[] getTermini(String[] dokumenti)
            {
                String[] pomDokument;
                String pomText = "";
                String[] rezultat;
                for (int i = 0; i < dokumenti.Length; i++)
                {

                    dokumenti[i] = dokumenti[i].Replace(" AND ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" OR ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" OF ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" IN ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" BY ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" FOR ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" ON ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" TO ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" THE ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" A ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" AN ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" AT ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" IS ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" IF ", " ");

                    dokumenti[i] = dokumenti[i].Replace(" И ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" ИЛИ ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" ОД ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" ВО ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" ДО ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" ЗА ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" НА ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" КОН ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" А ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" Е ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" У ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" В ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" ПОД ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" НАД ", " ");
                    dokumenti[i] = dokumenti[i].Replace(" АКО ", " ");

                    pomDokument = dokumenti[i].Split(' ', '.', ',', ':', ';', '?', '!', '@', '<', '>', '/', '(', ')', '-', '+', '_', '=', '#', '[', ']', '|', '"', '\'', '\\', '*', '$', '@', '{', '}');
                    for (int j = 0; j < pomDokument.Length; j++)
                    {
                        if (!pomText.Contains(pomDokument[j]) && !pomDokument[j].Equals(""))
                            pomText += pomDokument[j] + " ";
                    }
                }

                String[] pom = pomText.Split(' ');
                rezultat = new String[pom.Length - 1];
                for (int i = 0; i < rezultat.Length; i++)
                {
                    rezultat[i] = pom[i];
                }
                return rezultat;
            }
        
            //matrica vo koja 0-tata kolona e ID-to na korinikot a 1-vata kolona e textot
            public String[][] getDocsOdKorisnicite()
            {
                String[][] podatoci;
                DataSet dataSet = new DataSet();
                String sql = "SELECT idUser, textZaAnaliza FROM PodatociZaAnaliza";

                SqlConnection connection = ConnectionMenager.GetConnection();
                SqlCommand command = new SqlCommand(sql, connection);
                command.CommandType = CommandType.Text;

                SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
                dataAdapter.Fill(dataSet, "PodatociZaAnaliza");

                int redici = dataSet.Tables["PodatociZaAnaliza"].Rows.Count;
                podatoci = new String[redici][];

                for (int i=0; i<redici; i++)
                {
                    podatoci[i] = new String[2];
                    
                    podatoci[i][0] = dataSet.Tables["PodatociZaAnaliza"].Rows[i]["idUser"].ToString();
                    podatoci[i][1] = (String) dataSet.Tables["PodatociZaAnaliza"].Rows[i]["textZaAnaliza"];
                }
                connection.Close();
                return podatoci;
            }

            //klucnite zborovi od reklamite
            public String[][] getKveriOdReklamite()
            {
                String[][] podatoci;
                DataSet dataSet = new DataSet();
                String sql = "SELECT idReklama, KlucniZborovi FROM PostavenaReklama WHERE Nacin = 1";

                SqlConnection connection = ConnectionMenager.GetConnection();
                SqlCommand command = new SqlCommand(sql, connection);
                command.CommandType = CommandType.Text;

                SqlDataAdapter dataAdapter = new SqlDataAdapter(command);
                dataAdapter.Fill(dataSet, "PostavenaReklama");

                int redici = dataSet.Tables["PostavenaReklama"].Rows.Count;
                podatoci = new String[redici][];

                for (int i=0; i<redici; i++)
                {
                    podatoci[i] = new String[2];

                    podatoci[i][0] = dataSet.Tables["PostavenaReklama"].Rows[i]["idReklama"].ToString();
                    podatoci[i][1] = (String)dataSet.Tables["PostavenaReklama"].Rows[i]["KlucniZborovi"];
                }
                connection.Close();
                return podatoci;
            }

          
            public void analizaIZapisVoBaza()
            {
                int idBrojac = 1;

                String sql = "DELETE FROM ReklamiZaKorisnici";
                SqlConnection connection = ConnectionMenager.GetConnection();
                SqlCommand command = new SqlCommand(sql, connection);
                command.CommandType = CommandType.Text;
                command.ExecuteNonQuery();
                connection.Close();
                           
                String[][] docs = getDocsOdKorisnicite();
                String[][] keywords = getKveriOdReklamite();

                String[] textoviZaAnaliza = new String[docs.Length]; //dokumenti za analiza od korisnicite
                String[] keywordsOdReklami = new String[keywords.Length]; //klucnite zborovi od reklamite

                int[] idUsers = new int[docs.Length]; //id's na korisnicite
                int[] idReklami = new int[keywords.Length]; //id's na reklamite
                
                for ( int i=0; i<docs.Length; i++)
                {
                    idUsers[i] = int.Parse(docs[i][0]);
                    textoviZaAnaliza[i] = docs[i][1].ToUpper();
                }
                for ( int i=0; i<keywords.Length; i++)
                {
                    idReklami[i] = int.Parse(keywords[i][0]);
                    keywordsOdReklami[i] = keywords[i][1].ToUpper();
                }

                String[] termini = getTermini(textoviZaAnaliza);
                double[][] matA = matricaA(termini, textoviZaAnaliza);

                //dolzini na vektorite na A
                double[] dolzinaVektoriA = dolziniNaVektoriteNaA(matA);
                //matricata A(u)
                double[][] matAu = matricaAu(matA);

                String query;
                //za sekoja reklama posebno kveri.. gi vrtam site reklami i vrednostite direkt vo baza
                for (int i = 0; i < keywordsOdReklami.Length; i++)
                {
                    query = keywordsOdReklami[i].ToUpper();
                    double[] vektor = queryVektor(termini, query);
                    //dolzina na vektor na Q
                    double dolzinaVektorQ = dolzinaNaVektorotNaQ(vektor);
                    //vektorot q(u)
                    double[] vektorU = queryVektorU(vektor);
                    //rezultatot t.e. vrednostite na dokumentite od interes - nesortirani
                    double[] rezultat = mnozenjeNaMatrici(vektorU, matAu);

                    // bubble sort--------
                    int x = rezultat.Length;
                    double tempRezValue;
                    int tempUserId;

                    for (int ii = (x - 1); ii >= 0; ii--)
                    {
                        for (int jj = 1; jj <= ii; jj++)
                        {
                            if (rezultat[jj - 1] > rezultat[jj])
                            {
                                tempRezValue = rezultat[jj - 1];
                                rezultat[jj - 1] = rezultat[jj];
                                rezultat[jj] = tempRezValue;
                                //--
                                tempUserId = idUsers[jj - 1];
                                idUsers[jj - 1] = idUsers[jj];
                                idUsers[jj] = tempUserId;
                            }
                        }
                    }//end bubble

                    //postravuvanje vo bazata -- se zemaat do predvid samo dokumentite t.e korisnicite so koeficient >0

                    
                    for (int k = rezultat.Length-1; k >= 0; k--)
                    {
                        if (rezultat[k] > 0)
                        {
                            connection = ConnectionMenager.GetConnection();
                            
                            sql = "INSERT INTO ReklamiZaKorisnici (idRZK, idReklama, idUser, rezultat) VALUES ('" + idBrojac + "', '" + idReklami[i] + "', '" + idUsers[k] + "', '" + rezultat[k].ToString() + "')";
                            idBrojac++;
                            SqlCommand command2 = new SqlCommand(sql, connection);
                            command2.CommandType = CommandType.Text;
                            command2.ExecuteNonQuery();
                            connection.Close();
                        }
                    }

                }//end glavniot FOR za vrtenje na reklamite

                zapisSopredParametri(idBrojac);

            }

            //raspredelba na reklamite spored dadeni parametri 
            //idReklama, Lokacija, Pol, VozrastOd, VozrastDo
            public void zapisSopredParametri(int counter)
            {
                SqlConnection connection = ConnectionMenager.GetConnection();
                reklamaEditor re = new reklamaEditor();
                DataSet reklami = re.getAllParametarskiReklami();
                int idReklama, VozrastOd, VozrastDo;
                String Lokacija, Pol;
                String sql = "";
                DataSet korisnici;

                for (int i = 0; i < reklami.Tables[0].Rows.Count; i++)
                {
                    idReklama = Int32.Parse(reklami.Tables[0].Rows[i]["idReklama"].ToString());
                    Lokacija = reklami.Tables[0].Rows[i]["Lokacija"].ToString();
                    Pol = reklami.Tables[0].Rows[i]["Pol"].ToString();
                    VozrastOd = Int32.Parse(reklami.Tables[0].Rows[i]["VozrastOd"].ToString());
                    VozrastDo = Int32.Parse(reklami.Tables[0].Rows[i]["VozrastDo"].ToString());

                    if (Lokacija.Equals("Сите градови"))
                    {
                        if(Pol.Equals("Не е важен"))
                        {
                            korisnici = ReturnDataSet.ReturSet("SELECT idUser FROM Users, Age WHERE Age.idAge = Users.idAge AND Age.fromAge >= '" + VozrastOd + "' AND Age.toAge <= '" + VozrastDo + "'");
                        }
                        else
                        {
                            korisnici = ReturnDataSet.ReturSet("SELECT idUser FROM Users, Age, Sex WHERE Age.idAge = Users.idAge AND Sex.idSex = Users.idSex AND Age.fromAge >= '" + VozrastOd + "' AND Age.toAge <= '" + VozrastDo + "' AND Sex.sex = '" + Pol + "'");
                        }
                    }
                    else
                     // da dopravam po parametar grad koga ke se osposobi bazata!!!!!!!!!!!!!!!!!!!!!!!!!!
                    {
                        if (Pol.Equals("Не е важен"))
                        {
                            korisnici = ReturnDataSet.ReturSet("SELECT idUser FROM Users, Age WHERE Age.idAge = Users.idAge AND Age.fromAge >= '" + VozrastOd + "' AND Age.toAge <= '" + VozrastDo + "'");
                        }
                        else
                        {
                            korisnici = ReturnDataSet.ReturSet("SELECT idUser FROM Users, Age, Sex WHERE Age.idAge = Users.idAge AND Sex.idSex = Users.idSex AND Age.fromAge >= '" + VozrastOd + "' AND Age.toAge <= '" + VozrastDo + "' AND Sex.sex = '" + Pol + "'");
                        }
                    }

                    for (int j = 0; j < korisnici.Tables[0].Rows.Count; j++)
                    {
                        int idUser = Int32.Parse(korisnici.Tables[0].Rows[0][0].ToString());
                        connection = ConnectionMenager.GetConnection();
                        counter++;
                        sql = "INSERT INTO ReklamiZaKorisnici (idRZK, idReklama, idUser, rezultat) VALUES ('" + counter + "', '" + idReklama + "', '" + idUser + "', '" + 1 + "')";
                        SqlCommand command2 = new SqlCommand(sql, connection);
                        command2.CommandType = CommandType.Text;
                        command2.ExecuteNonQuery();
                        connection.Close();
                    }

                }//kraj na for za reklamite
            }


    }
}


